#include "mysocket.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <conio.h>

using namespace std;

// ==================== NetworkManager 实现 ====================

NetworkManager::NetworkManager() : clientSocket(INVALID_SOCKET), isInitialized(false), connected(false) {
}

NetworkManager::~NetworkManager() {
    disconnect();
    if (isInitialized) {
        cleanupWinsock();
    }
}

bool NetworkManager::initialize() {
    if (isInitialized) return true;

    if (!initWinsock()) {
        cout << "Network protocol stack initialization failed!" << endl;
        return false;
    }

    isInitialized = true;
    return true;
}

bool NetworkManager::initWinsock() {
    WSADATA wsaData;
    WORD version = MAKEWORD(2, 2);
    return WSAStartup(version, &wsaData) == 0;
}

bool NetworkManager::connectToServer(const string& serverAddress, int port) {
    if (!isInitialized) {
        cout << "Network manager not initialized!" << endl;
        return false;
    }

    // 创建客户端socket
    clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (clientSocket == INVALID_SOCKET) {
        cout << "Failed to create client socket!" << endl;
        return false;
    }

    // 设置服务器地址
    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);
    inet_pton(AF_INET, serverAddress.c_str(), &serverAddr.sin_addr);

    // 连接到服务器
    if (connect(clientSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
        cout << "Failed to connect to server!" << endl;
        closesocket(clientSocket);
        clientSocket = INVALID_SOCKET;
        return false;
    }

    connected = true;
    cout << "Successfully connected to database server " << serverAddress << ":" << port << endl;
    return true;
}

void NetworkManager::disconnect() {
    if (clientSocket != INVALID_SOCKET) {
        closesocket(clientSocket);
        clientSocket = INVALID_SOCKET;
    }
    connected = false;
}

bool NetworkManager::isConnected() const {
    return connected && clientSocket != INVALID_SOCKET;
}

SOCKET NetworkManager::getSocket() const {
    return clientSocket;
}

void NetworkManager::cleanupWinsock() {
    WSACleanup();
}

// ==================== MessageTransporter 实现 ====================

MessageTransporter::MessageTransporter(SOCKET socket) : socket(socket) {
}

bool MessageTransporter::sendMessage(const string& message) {
    if (socket == INVALID_SOCKET) {
        return false;
    }

    // 只发送字符串内容，不包含额外的null终止符
    int result = send(socket, message.c_str(), message.length(), 0);
    return result != SOCKET_ERROR;
}

string MessageTransporter::receiveMessage() {
    if (socket == INVALID_SOCKET) {
        return "";
    }

    char buffer[BUFFER_SIZE + 5];
    int bytesReceived = recv(socket, buffer, BUFFER_SIZE, 0);

    if (bytesReceived > 0) {
        // 确保缓冲区以null结尾，但不覆盖接收到的数据
        if (bytesReceived < BUFFER_SIZE) {
            buffer[bytesReceived] = '\0';
        } else {
            buffer[BUFFER_SIZE - 1] = '\0';
        }
        
        // 如果接收到的数据已经包含null终止符，创建字符串时会自动处理
        return string(buffer);
    }

    return "";
}

bool MessageTransporter::isConnectionAlive() {
    return socket != INVALID_SOCKET;
}

// ==================== AuthenticationHandler 实现 ====================

AuthenticationHandler::AuthenticationHandler(shared_ptr<MessageTransporter> transporter)
    : messageTransporter(transporter) {
}

bool AuthenticationHandler::performAuthentication() {
    cout << "=== Database User Authentication ===" << endl;

    while (true) {
        string username, password;

        // 获取用户凭据
        if (!requestCredentials(username, password)) {
            return false; // 用户选择退出
        }

        // 验证凭据
        if (validateCredentials(username, password)) {
            authenticatedUsername = username;
            cout << "Authentication successful! Welcome, " << username << "!" << endl;
            return true;
        }
        else {
            cout << "Authentication failed, please try again" << endl;
        }
    }
}

bool AuthenticationHandler::requestCredentials(string& username, string& password) {
    cout << "Please enter username (type 'exit' to quit): "<<flush;
    getline(cin, username);

    if (username == "exit") {
        return false;
    }

    cout << "Please enter password: ";

    // 发送密码
    password = "";
    char ch;
    while ((ch = _getch()) != '\r') {
        if (ch == '\b') { // 退格键
            if (!password.empty()) {
                password.pop_back();
                cout << "\b \b";
            }
        }
        else {
            password += ch;
            cout << '*';
        }
    }
    cout << endl;

    return true;
}

bool AuthenticationHandler::validateCredentials(const string& username, const string& password) {
    // 发送用户名
    if (!messageTransporter->sendMessage(username)) {
        cout << "Failed to send username!" << endl;
        return false;
    }

    // 发送密码
    if (!messageTransporter->sendMessage(password)) {
        cout << "Failed to send password!" << endl;
        return false;
    }

    // 接收验证结果
    string response = messageTransporter->receiveMessage();

    if (response == "pass") {
        return true;
    }
    else {
        cout << response; // 显示服务器返回的错误信息
        return false;
    }
}

string AuthenticationHandler::getAuthenticatedUsername() const {
    return authenticatedUsername;
}

// ==================== CommandProcessor 实现 ====================

CommandProcessor::CommandProcessor(shared_ptr<MessageTransporter> transporter)
    : messageTransporter(transporter) {
}

void CommandProcessor::startCommandLoop() {
    cout << "\n=== Database Command Interface ===" << endl;
 

    while (true) {
        string command = getUserInput();

        //9.16
        // 命令为空，继续循环
        if (command.empty()) {
            continue;
        }

        if (isExitCommand(command)) {
            cout << "Exiting.." << endl;
            break;
        }

        if (!processCommand(command)) {
            cout << "[ERROR] SQL sending failed" << endl;
            break;
        }
    }
}

void CommandProcessor::executeScript(const string& scriptFile) {
    cout << "\n=== Executing SQL Script File ===" << endl;
    cout << "[INFO] Executing script: " << scriptFile << endl;
    
    ifstream file(scriptFile);
    if (!file.is_open()) {
        cout << "[ERROR] Cannot open script file: " << scriptFile << endl;
        return;
    }
    
    string line;
    string command;
    int lineNumber = 0;
    int executedCommands = 0;
    
    while (getline(file, line)) {
        lineNumber++;
        
        // 跳过空行，但输出注释行
        if (line.empty()) {
            continue;
        }
        
        // 如果是注释行，直接输出并继续
        if (line[0] == '#' || line.substr(0, 2) == "--") {
            cout << "[COMMENT] " << line << endl;
            continue;
        }
        
        // 累积多行命令（以分号结尾）
        command += line + " ";
        
        // 如果命令以分号结尾，执行它
        if (line.back() == ';') {
            // 移除末尾多余的空格，但保留分号
            while (!command.empty() && command.back() == ' ') {
                command.pop_back();
            }
            
            cout << "\n[INFO] Executing command #" << (++executedCommands) << ": " << command << endl;
            
            if (!processCommand(command)) {
				cout << "[ERROR] Script execution failed, stopping subsequent commands (line " << lineNumber << ")" << endl;
                file.close();
                return;
            }
            
            command.clear();
        }
    }
    
    // 处理最后一个没有分号的命令
    if (!command.empty()) {
        cout << "\n[INFO] Executing last command " << command << endl;
        if (!processCommand(command))
        {
            cout << "[ERROR] Script execution failed " << endl;
        }
        else {
            executedCommands++;
        }
    }
    
    file.close();
    cout << "\n=== Script execution completed, executed " << executedCommands << " commands ===" << endl;
}

bool CommandProcessor::processCommand(const string& command) {
    // 发送命令到服务器
    //9.16
    // 命令为空，不做任何处理
    if (command.empty()) {
        return true;
    }


    // 发送消息失败
    if (!messageTransporter->sendMessage(command)) {
        return false;
    }

    // 接收并显示结果
    string result = messageTransporter->receiveMessage();
    if (result.empty()) {
        return false;
    }

    displayResult(result);
    return true;
}

string CommandProcessor::getUserInput() {
    cout << "\nSQL> ";
    string input;
    getline(cin, input);

    //9.16
    // 输入为空，返回空字符串
    if (input.empty()) {
        return "";
    }

    return input;
}

void CommandProcessor::displayResult(const string& result) {
    cout << "\n--- Execution Result ---" << endl;
    cout << result << endl;
    cout << "--- Result End ---" << endl;
}

bool CommandProcessor::isExitCommand(const string& command) {
    return command == "exit" || command == "EXIT" || command == "quit" || command == "QUIT";
}

bool CommandProcessor::confirmScriptExecution(const string& scriptFile) {
    cout << "\n=== Script Execution Confirmation ===" << endl;
    cout << "[INFO] Found SQL script file: " << scriptFile << endl;
    cout << "[INFO] Do you want to execute this script? (y/n): ";
    
    string response;
    getline(cin, response);
    
    if (response == "y" || response == "Y" || response == "yes" || response == "YES") {
        return true;
    } else {
        cout << "[INFO] User cancelled script execution" << endl;
        return false;
    }
}

// ==================== DatabaseClient 实现 ====================

DatabaseClient::DatabaseClient() : connectionState(ClientConnectionState::DISCONNECTED) {
    networkManager = make_unique<NetworkManager>();
}

DatabaseClient::~DatabaseClient() {
    disconnect();
}

bool DatabaseClient::initialize() {
    if (!networkManager->initialize()) {
        cout << "Client initialization failed!" << endl;
        return false;
    }

    cout << "Client initialization successful!" << endl;
    return true;
}

bool DatabaseClient::connectToServer(const string& serverAddress, int port) {
    if (connectionState != ClientConnectionState::DISCONNECTED) {
        cout << "Client is already connected or connecting!" << endl;
        return false;
    }

    if (!networkManager->connectToServer(serverAddress, port)) {
        return false;
    }

    connectionState = ClientConnectionState::CONNECTED;

    // 创建消息传输器
    messageTransporter = make_shared<MessageTransporter>(networkManager->getSocket());

    // 创建验证处理器
    authHandler = make_unique<AuthenticationHandler>(messageTransporter);

    // 创建命令处理器
    commandProcessor = make_unique<CommandProcessor>(messageTransporter);

    return true;
}

void DatabaseClient::startSession() {
    if (connectionState != ClientConnectionState::CONNECTED) {
        cout << "Please connect to server first!" << endl;
        return;
    }

    // 执行身份验证
    if (!authHandler->performAuthentication()) {
        
        disconnect();
        return;
    }

    connectionState = ClientConnectionState::AUTHENTICATED;

    // 开始命令循环
    commandProcessor->startCommandLoop();

    // 发送退出命令
    messageTransporter->sendMessage("exit");

    disconnect();
}

void DatabaseClient::startScriptSession(const string& scriptFile) {
    if (connectionState != ClientConnectionState::CONNECTED) {
        cout << "Please connect to server first!" << endl;
        return;
    }

    // 执行身份验证
    if (!authHandler->performAuthentication()) {
        cout << "Authentication failed or user cancelled" << endl;
        disconnect();
        return;
    }

    connectionState = ClientConnectionState::AUTHENTICATED;
    cout << "[INFO] Authentication successful!" << endl;

    // 用户确认是否执行脚本
    if (commandProcessor->confirmScriptExecution(scriptFile)) {
        cout << "[INFO] Starting script execution.." << endl;
        // 执行脚本文件
        commandProcessor->executeScript(scriptFile);
    } else {
        cout << "[INFO] Script execution cancelled, entering interactive mode" << endl;
        // 进入交互模式
        commandProcessor->startCommandLoop();
    }

    // 发送退出命令
    messageTransporter->sendMessage("exit");

    disconnect();
}

void DatabaseClient::disconnect() {
    if (connectionState != ClientConnectionState::DISCONNECTED) {
        cleanup();
        networkManager->disconnect();
        connectionState = ClientConnectionState::DISCONNECTED;
		cout << "Client connection disconnected!" << endl;
    }
}

void DatabaseClient::cleanup() {
    commandProcessor.reset();
    authHandler.reset();
    messageTransporter.reset();
}
